package org.ws.httphelper.support.parser.field.operator;

import org.jsoup.nodes.Element;
import org.w3c.dom.Node;
import org.ws.httphelper.core.parser.ParseOperator;
import org.ws.httphelper.model.field.ExpressionType;
import org.ws.httphelper.model.field.ParseField;
import org.ws.httphelper.model.field.ParseFieldType;
import org.ws.httphelper.support.parser.field.ParseOperatorFactory;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;

public abstract class AbstractParseOperator<T> implements ParseOperator {

    protected abstract String evaluateString(ParseField parseField, T source)throws Exception;
    protected abstract List evaluateList(ParseField parseField, T source)throws Exception;
    protected abstract Map evaluateMap(ParseField parseField, T source)throws Exception;

    protected void evaluateChild(List<ParseField> childFieldList, T source, Map map)throws Exception {
        for(ParseField childFieldInfo:childFieldList){
            String name = childFieldInfo.getFieldName();
            Object value = null;
            // 若表达式类型位Regex：可以与其他表达式混合使用
            if(childFieldInfo.getExpressionType() == ExpressionType.REGEX){
                String sourceHtml = null;
                if(source instanceof Element){
                    sourceHtml = ((Element)source).html();
                }
                else if(source instanceof Node){
                    StringWriter writer = new StringWriter();
                    Transformer transformer = TransformerFactory.newInstance().newTransformer();
                    transformer.transform(new DOMSource((Node) source), new StreamResult(writer));
                    sourceHtml = writer.toString();
                }
                else {
                    sourceHtml = (String) source;
                }
                RegexParseOperator parseOperator = (RegexParseOperator) ParseOperatorFactory.getInstance().getParseOperator(ExpressionType.REGEX);
                if(childFieldInfo.getFieldType() == ParseFieldType.STRING){
                    value = parseOperator.evaluateString(childFieldInfo,sourceHtml);
                }
                else if(childFieldInfo.getFieldType() == ParseFieldType.LIST){
                    value = parseOperator.evaluateList(childFieldInfo,sourceHtml);
                }
                else if(childFieldInfo.getFieldType() == ParseFieldType.OBJECT){
                    value = parseOperator.evaluateMap(childFieldInfo,sourceHtml);
                }
            }
            else {
                // 非REGEX：子属性必须与父属性解析类型一致
                if(childFieldInfo.getFieldType() == ParseFieldType.STRING){
                    value = evaluateString(childFieldInfo,source);
                }
                else if(childFieldInfo.getFieldType() == ParseFieldType.LIST){
                    value = evaluateList(childFieldInfo,source);
                }
                else if(childFieldInfo.getFieldType() == ParseFieldType.OBJECT){
                    value = evaluateMap(childFieldInfo,source);
                }
            }
            map.put(name,value);
        }
    }
}
